#include <functional>
#include <memory>
#include <string>
#include <sys/socket.h>
#include <unistd.h>
#include <cassert>
#include "Buffer.h"
#include "Channel.h"
#include "TaskQueue.h"

namespace GiSo {

//TODO: 不再暴露writeCallBack,而是设置writeCompletition，由库自行处理写操作，写完后再调用writeCompletitionCallBack

class TcpConnection : public std::enable_shared_from_this<TcpConnection> {
public:

    using Ptr = std::shared_ptr<TcpConnection>;

    using ReadCallback  = std::function<void(Ptr,Buffer&)>;
    using CloseCallback = std::function<void(Ptr)>;  // 会立即执行，所以使用shared_ptr
    using WriteCallback = std::function<void(Ptr)>;

    TcpConnection(std::unique_ptr<Channel> channel,TaskQueue::Ptr taskQueue);

    ~TcpConnection();

    /**
     * @brief 发送数据.
     * 
     * @param data 
     * @return bool(返回false表示缓冲区满了)
     */
    bool Send(const std::string& data);
    bool Send(const std::vector<char>& data);
    bool Send(const void* data, size_t len);

    // 主动关闭连接(即使重复调用也不会有问题)
    void Close();

    void EnableReading(){
        m_Channel->EnableReading();
        m_Reading = true;
    }

    void DisableReading(){
        m_Channel->DisableReading();
        m_Reading = false;
    }

    void EnableWriting(){
        m_Channel->EnableWriting();
        m_Writing = true;
    }

    void DisableWriting(){
        m_Channel->DisableWriting();
        m_Writing = false;
    }

    void ClearWriteBuffer(){
        m_OutputBuffer.Clear();
    }

    // 设置各类回调
    void SetReadCallback(ReadCallback cb){m_ReadCallback = std::move(cb);}
    void SetCloseCallback(CloseCallback cb){m_CloseCallback = std::move(cb);}
    void SetWriteCompleteCallback(WriteCallback cb){m_WriteCompleteCallback = std::move(cb);}
    void SetRemoveFromContainerCallback(CloseCallback cb) { m_RemoveFromContainerCallback = std::move(cb); }

    int GetFd() const { return m_Channel->GetFd(); }

private:

    void HandleRead();

    void HandleWrite();

    void HandleClose();

    void HandleError();

    std::unique_ptr<Channel> m_Channel;
    Buffer m_InputBuffer;   // 接收缓冲区
    Buffer m_OutputBuffer;  // 发送缓冲区

    // 回调函数
    ReadCallback m_ReadCallback;    // 读回调，这个回调应该在worker线程中执行
    CloseCallback m_CloseCallback;  // 连接断开之后的回调，不管是对端关闭还是自己关闭,这个是用给Connection的用户使用的
    WriteCallback m_WriteCompleteCallback;  // 写回调，这个回调应该在worker线程中执行
    CloseCallback m_RemoveFromContainerCallback;  // 从容器中移除该连接的回调，这个回调应该在主线程中执行

    // 任务队列 (如果是单线程模式，两个队列是一样的)（reactor模式下TaskQueue是Worker线程的，MainQueue是主线程的）
    std::shared_ptr<TaskQueue> m_TaskQueue;

    std::atomic<bool> m_Running = true; // 连接是否在运行中
    bool m_Writing = false; // 连接是否允许处理写操作
    bool m_Reading = false; // 连接是否在允许处理读操作
    std::string m_WriteData; // 发送的数据

};

}